package com.hexiang.book.dao.impl;

import com.hexiang.book.dao.BookRepository;
import com.hexiang.book.dao.BookRowMapper;
import com.hexiang.book.domain.Book;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 使用JdbcTemplate来完成书籍数据库操作
 */
@Repository("jdbcBookRepository")
@Slf4j
public class JdbcBookRepository implements BookRepository {

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private BookRowMapper bookRowMapper;

    @Override
    public int count() {
        return jdbcTemplate.queryForObject("select count(*) from t_book", Integer.class);
    }

    @Override
    public int save(Book book) {
        return jdbcTemplate.update("insert into t_book (name, price,create_time,modify_time) values(?,?,?,?)", book.getName(), book.getPrice(), LocalDateTime.now(), LocalDateTime.now());
    }

    @Override
    public int update(Book book) {
        return jdbcTemplate.update("update t_book set price = ? , modify_time=now() where id = ?", book.getPrice(), book.getId());
    }

    @Override
    public int deleteById(Long id) {
        return jdbcTemplate.update("delete t_book where id = ?", id);
    }

    @Override
    public List<Book> findAll() {
        return jdbcTemplate.query("select * from t_book", bookRowMapper);
    }

    @Override
    public Book findById(Long id) {
        return jdbcTemplate.queryForObject("select * from t_book where id = ?", new Object[]{id}, bookRowMapper);
    }

    @Override
    public List<Book> findByNameAndPrice(String name, BigDecimal price) {
        return jdbcTemplate.query("select * from t_book where name like ? and price <= ?", new Object[]{"%" + name + "%", price}, bookRowMapper);
    }

    @Override
    public String findNameById(Long id) {
        return jdbcTemplate.queryForObject("select name from t_book where id = ?", new Object[]{id}, String.class);
    }

    @Override
    public int[] batchUpdate(List<Book> bookList) {

        return this.jdbcTemplate.batchUpdate("update t_book set price = ? , modify_time=now() where id = ?",
                new BatchPreparedStatementSetter() {

                    @Override
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                        ps.setBigDecimal(1, bookList.get(i).getPrice());
                        ps.setLong(2, bookList.get(i).getId());
                    }

                    @Override
                    public int getBatchSize() {
                        return bookList.size();
                    }

                });

    }

    @Override
    public int[][] batchUpdate(List<Book> bookList, int batchSize) {

        int[][] updateCounts = jdbcTemplate.batchUpdate("update t_book set price = ? where id = ?",
                bookList,
                batchSize,
                new ParameterizedPreparedStatementSetter<Book>() {
                    @Override
                    public void setValues(PreparedStatement ps, Book argument) throws SQLException {
                        ps.setBigDecimal(1, argument.getPrice());
                        ps.setLong(2, argument.getId());
                    }
                });
        return updateCounts;

    }

    @Override
    public int[] batchInsert(List<Book> bookList) {

        return this.jdbcTemplate.batchUpdate(
                "insert into t_book (name, price) values(?,?)",
                new BatchPreparedStatementSetter() {

                    @Override
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                        ps.setString(1, bookList.get(i).getName());
                        ps.setBigDecimal(2, bookList.get(i).getPrice());
                    }

                    @Override
                    public int getBatchSize() {
                        return bookList.size();
                    }

                });
    }

    @Override
    public int[][] batchInsert(List<Book> bookList, int batchSize) {

        int[][] updateCounts = jdbcTemplate.batchUpdate(
                "insert into t_book (name, price) values(?,?)",
                bookList,
                batchSize,
                new ParameterizedPreparedStatementSetter<Book>() {
                    @Override
                    public void setValues(PreparedStatement ps, Book argument) throws SQLException {
                        ps.setString(1, argument.getName());
                        ps.setBigDecimal(2, argument.getPrice());
                    }
                });
        return updateCounts;

    }

}